package com.webchat.pgc.service.sys;

import com.webchat.common.bean.APIPageResponseBean;
import com.webchat.common.enums.RedisKeyEnum;
import com.webchat.common.exception.BusinessException;
import com.webchat.common.service.RedisService;
import com.webchat.common.util.JsonUtil;
import com.webchat.domain.vo.request.sys.SysDataDictionaryDetailRequestVo;
import com.webchat.domain.vo.response.sys.SysDataDictionaryBaseVO;
import com.webchat.domain.vo.response.sys.SysDataDictionaryDetailBaseVO;
import com.webchat.pgc.repository.dao.sys.ISysDataDictionaryDAO;
import com.webchat.pgc.repository.dao.sys.ISysDataDictionaryDetailDAO;
import com.webchat.pgc.repository.entity.sys.SysDataDictionaryDetail;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据字典详情服务
 *
 * @author SongRenShuo
 * @date 2025/06/25
 */
@Service
public class SysDataDictionaryDetailService {

    @Autowired
    private ISysDataDictionaryDetailDAO sysDataDictionaryDetailDAO;
    @Autowired
    private RedisService redisService;
    @Autowired
    private ISysDataDictionaryDAO sysDataDictionaryDAO;

    /**
     * 创建或者更新数据字典详情
     *
     * @param requestVO 请求 VO
     * @return {@link Long }
     */
    public Long save(SysDataDictionaryDetailRequestVo requestVO) {
        // 1.参数校验
        parameterValidation(requestVO);
        // 2.新增或修改数据
        Long id = requestVO.getId();
        if (id == null) {
            // 新增数据
            long countDistinctByCode = sysDataDictionaryDetailDAO.countDistinctByDataDictionaryIdAndCode(requestVO.getDataDictionaryId(), requestVO.getCode());
            Assert.isTrue(countDistinctByCode == 0, "字典详情编码已存在");
            long countDistinctByName = sysDataDictionaryDetailDAO.countDistinctByDataDictionaryIdAndName(requestVO.getDataDictionaryId(), requestVO.getName());
            Assert.isTrue(countDistinctByName == 0, "字典详情名称已存在");
        } else {
            // 修改数据
            long countDistinctByCode = sysDataDictionaryDetailDAO.countDistinctByDataDictionaryIdAndCodeAndIdNot(requestVO.getDataDictionaryId(), requestVO.getCode(), id);
            Assert.isTrue(countDistinctByCode == 0, "字典详情编码已存在");
            long countDistinctByName = sysDataDictionaryDetailDAO.countDistinctByDataDictionaryIdAndNameAndIdNot(requestVO.getDataDictionaryId(), requestVO.getName(), id);
            Assert.isTrue(countDistinctByName == 0, "字典详情名称已存在");
        }
        SysDataDictionaryDetail dictionaryDetail = convert(requestVO);
        id = sysDataDictionaryDetailDAO.save(dictionaryDetail).getId();
        // 3.清除缓存
        this.removeCache(dictionaryDetail.getDataDictionaryId());
        return id;
    }

    /**
     * 删除数据字典详情
     *
     * @param detailId 数据字典详情主键
     * @param userId   用户 ID
     * @return boolean
     */
    public boolean delete(Long detailId, String userId) {
        Assert.notNull(detailId, "字典详情ID不能为空");
        SysDataDictionaryDetail dictionaryDetail = sysDataDictionaryDetailDAO.findById(detailId)
                .orElseThrow(() -> new BusinessException("字典详情信息不存在：" + detailId));

        sysDataDictionaryDetailDAO.deleteById(detailId);
        // 清除缓存
        this.removeCache(dictionaryDetail.getDataDictionaryId());
        return true;
    }

    /**
     * 分页查询数据字典详情
     *
     * @param dataDictionaryId     数据字典ID
     * @param code             编号
     * @param name             名称
     * @param pageNo           页码
     * @param pageSize         每页条数
     * @return {@link APIPageResponseBean }<{@link SysDataDictionaryDetailBaseVO }>
     */
    public APIPageResponseBean<SysDataDictionaryDetailBaseVO> page(Long dataDictionaryId, String code, String name, Integer pageNo, Integer pageSize) {
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.ASC, "orderNo"));

        boolean notBlankCode = StringUtils.isNotBlank(code);
        boolean notBlankName = StringUtils.isNotBlank(name);

        Page<SysDataDictionaryDetail> dataDictionaryCategoryEntities = sysDataDictionaryDetailDAO
                .findByDataDictionaryIdAndCodeAndNameLike(dataDictionaryId,
                        notBlankCode ? code : null,
                        notBlankName ? name : null, pageable);

        List<SysDataDictionaryDetailBaseVO> vos = new ArrayList<>();
        long totalElements = 0L;
        if (dataDictionaryCategoryEntities != null && CollectionUtils.isNotEmpty(dataDictionaryCategoryEntities.getContent())) {
            totalElements = dataDictionaryCategoryEntities.getTotalElements();
            vos = dataDictionaryCategoryEntities.getContent().stream().map(this::convert).collect(Collectors.toList());
        }
        return APIPageResponseBean.success(pageNo, pageSize, totalElements, vos);
    }

    /**
     * 获取数据字典详情列表
     *
     * @param dataDictionaryBaseVO 数据字典
     * @return {@link Map }<{@link String },{@link String }>
     */
    public Map<String, String> detail(SysDataDictionaryBaseVO dataDictionaryBaseVO) {
        Assert.notNull(dataDictionaryBaseVO, "数据字典信息不存在");
        Long dataDictionaryId = dataDictionaryBaseVO.getId();
        String key = getKey(dataDictionaryId);
        String cache = redisService.get(key);
        if (StringUtils.isBlank(cache)) {
            // 刷新数据字典缓存
            return this.refreshCache(dataDictionaryId);
        }
        return JsonUtil.fromJson(cache, Map.class);
    }

    /**
     * 清除验证
     *
     * @param requestVO 请求 VO
     */
    private static void parameterValidation(SysDataDictionaryDetailRequestVo requestVO) {
        Assert.hasText(requestVO.getCode(), "字典详情编码不能为空");
        Assert.hasText(requestVO.getName(), "字典详情名称不能为空");
        Assert.notNull(requestVO.getDataDictionaryId(), "数据字典ID不能为空");
        Assert.notNull(requestVO.getOrderNo(), "排序编号不能为空");
    }

    /**
     * 获取Redis缓存Key
     *
     * @param dataDictionaryId 数据字典 ID
     * @return {@link String }
     */
    private static String getKey(Long dataDictionaryId) {
        return RedisKeyEnum.SYS_DATA_DICTIONARY_DETAIL_CACHE.getKey(dataDictionaryId.toString());
    }

    /**
     * 刷新缓存
     *
     * @param dataDictionaryId 数据字典 ID
     */
    public Map<String, String> refreshCache(Long dataDictionaryId) {
        Map<String, String> dataDictionaryDetailMap = new HashMap<>();
        sysDataDictionaryDetailDAO.findAllByDataDictionaryId(dataDictionaryId)
                .forEach(sysDataDictionaryDetail -> dataDictionaryDetailMap.put(sysDataDictionaryDetail.getCode(), sysDataDictionaryDetail.getName()));
        return this.refreshCache(dataDictionaryId, dataDictionaryDetailMap);
    }

    /**
     * 刷新缓存
     *
     * @param dataDictionaryId 数据字典 ID
     * @param dataDictionaryDetailMap 数据字典详情
     * @return {@link Map }<{@link String }, {@link String }>
     */
    public Map<String, String> refreshCache(Long dataDictionaryId, Map<String, String> dataDictionaryDetailMap) {
        if (dataDictionaryDetailMap == null) {
            return Collections.emptyMap();
        }
        String key = getKey(dataDictionaryId);
        redisService.set(key, JsonUtil.toJsonString(dataDictionaryDetailMap),
                RedisKeyEnum.SYS_DATA_DICTIONARY_DETAIL_CACHE.getExpireTime());
        return dataDictionaryDetailMap;
    }


    /**
     * 删除缓存
     *
     * @param dataDictionaryId 数据字典 ID
     */
    public void removeCache(Long dataDictionaryId) {
        String key = getKey(dataDictionaryId);
        redisService.remove(key);
    }

    /**
     * 转换
     *
     * @param requestVO 请求 VO
     * @return {@link SysDataDictionaryDetail }
     */
    private SysDataDictionaryDetail convert(SysDataDictionaryDetailRequestVo requestVO) {

        String operator = requestVO.getOperator();
        Long id = requestVO.getId();
        Date now = new Date();
        SysDataDictionaryDetail dataDictionaryDetail;
        if (id != null) {
            dataDictionaryDetail = sysDataDictionaryDetailDAO.findById(id).orElse(null);
            Assert.notNull(dataDictionaryDetail, "数据字典详情不存在");
        } else {
            dataDictionaryDetail = new SysDataDictionaryDetail();
            dataDictionaryDetail.setCreateBy(operator);
            dataDictionaryDetail.setCreateDate(now);
            dataDictionaryDetail.setDataDictionaryId(requestVO.getDataDictionaryId());
        }
        dataDictionaryDetail.setCode(requestVO.getCode());
        dataDictionaryDetail.setName(requestVO.getName());
        dataDictionaryDetail.setOrderNo(requestVO.getOrderNo());
        dataDictionaryDetail.setDescription(requestVO.getDescription());
        dataDictionaryDetail.setUpdateBy(operator);
        dataDictionaryDetail.setUpdateDate(now);
        return dataDictionaryDetail;
    }

    /**
     * 转换
     *
     * @return {@link SysDataDictionaryDetailBaseVO }
     */
    private SysDataDictionaryDetailBaseVO convert(SysDataDictionaryDetail dataDictionaryDetail) {
        if (dataDictionaryDetail == null) {
            return null;
        }
        SysDataDictionaryDetailBaseVO dataDictionaryCategoryBaseVo = new SysDataDictionaryDetailBaseVO();
        BeanUtils.copyProperties(dataDictionaryDetail, dataDictionaryCategoryBaseVo);
        return dataDictionaryCategoryBaseVo;
    }

}
